﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Net;
using System.Web;
using System.IO;
using System.Xml;
using Javavaj.iHunter;
using Javavaj.iHunter.Core;

namespace Javavaj.iHunter.ThuLearnChannels
{
    /*internal*/
    public class ThuLearnChannel : IChannel
    {
        //private const string UrlRoot = "http://learn.tsinghua.edu.cn";

        private string courseId;
        private string username;
        private string password;

        private string title = "";
        private string description = "";

        private CookieContainer cookies;
        
        private bool isOpened = false;
        private DateTime lastLoginTime = DateTime.MinValue;

        private static Regex regexNote = null;
        private static Regex regexNoteTitle = null;
        private static Regex regexFile = null;
        private static Regex regexHomework = null;
        private static Regex regexHomeworkScore = null;
        private static Regex regexDiscussTopic = null;
        private static Regex regexLz = null;
        private static Regex regexRe = null;
        private static Regex regexAttach = null;
        private static Regex regexTableItem = null;
        private static Regex regexEscape = null;

        static ThuLearnChannel()
        {

            regexNote = new Regex(@"<a href='[^&]*&(?<LinkId>[^']*)'>"
                                + @"(<font[^>]*>)*(?<Title>[^<]*)(</font>)*</a>"
                                + @"\s*</td>\s*<td[^>]*>"
                                + @"(?<Author>[^<]*)</td>"
                                + @"\s*<td[^>]*>(?<Date>\d{4}-\d\d-\d\d)", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.ExplicitCapture);
            
            regexNoteTitle = new Regex(@"<td[^>]*>(<font[^>]*>)*(?<Title>[^<]*)(</font>)*</td>", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);
            
            regexFile = new Regex("window.open[^&]*&getfilelink=(?<FileName>[^\"]*)&id=[^\n]*</a></td>-->"//FileName with _
                                + "\\s*<td[^>]*><a\\s+target=[^=]*=\"(?<Link>[^\"]*)\""                 //Link
                                + "[^>]*>(<font[^>]*>)*(?<Title>[^<]*)(</font>)*</a></td>"              //Message Title
                                + @"\s*<td[^>]*>(?<Content>[^<]*)</td>"                                 //Content
                                + @"\s*<td[^>]*>(?<Size>[^<]*)</td>"                                    //File Size (string)
                                + @"\s*<td[^>]*>(?<Date>\d{4}-\d\d-\d\d)</td>"                          //Date
                                , RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.ExplicitCapture);
            
            regexHomework = new Regex("(?<Link>hom_wk_detail\\.jsp\\?id=(?<Id>\\d*)[^\"]*)\">"
                                   + @"(?<Title>[^<]*)</a></td>"
                                   + @"\s*<td[^>]*>(?<PubTime>\d{4}-\d\d-\d\d)</td>"
                                   + @"\s*<td[^>]*>(?<DueTime>\d{4}-\d\d-\d\d)</td>"
                                   + @"\s*<td[^>]*>\s*(?<Status>\S*)\s*</td>"
                                   + @"\s*<td[^>]*>[^<]*</td>\s*<td[^>]*>\s*"
                                   + "<input id=\"submit_hw\" name=\"submit_hw\" value=\"[^\"]*\"(?<Submit>(?: disabled=\"true\")?)\\s*type[^']*'(?<SubmitPage>[^']*)'[^>]*>"
                                   + "\\s*<input id=\"lookinfo\" name=\"lookinfo\" value=\"[^\"]*\"(?<Score>(?: disabled=\"true\")?)\\s*type"
                                   , RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.ExplicitCapture);
            
            regexHomeworkScore = new Regex(@"<td[^>]*>(?<Teacher>[^\012\15]*)"
                                        + @"[^x]*[^>]*>(?<Date>\d{4}-\d\d-\d\d)"
                                        + @"[^x]*[^>]*>\s*(?<Score>[\d\.]*)"
                                        + @"[^x]*[^>]*>(?<Comment>[^<]*)"
                                        , RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);
            regexDiscussTopic = new Regex(@"<td[^>]*>\s*<a href='(?<Link>[^']*)'>(?<Title>[^<]*)</a>"
                                        + @"\s*</td>\s*<td[^>]*>(?<Author>[^<]*)</td>"
                                        + @"\s*<td[^>]*>(?<Amount>[^<]*)</td>"
                                        + @"\s*<td[^>]*>(?<PubTime>[^<]*)</td>"
                                        , RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture | RegexOptions.Compiled);

            regexLz = new Regex(@"讨论主题</td>\s*<td[^>]*><p[^>]*>(?<Title>[^<]*)(?(?!<tr>)\s*.)*?\s*<tr>\s*"
                              + @"<td[^>]*>\s*发表人</td>\s*"
                              + @"<td[^>]*><p[^>]*>(?<Author>[^<]*)</p></td>\s*"
                              + @"<td[^>]*>[^<]*</td>\s*"
                              + @"<td[^>]*><p[^>]*>(?<PubTime>[^<]*)</p></td>\s*</tr>\s*<tr>\s*"
                              + @"<td[^>]*>[^<]*</td>\s*<td[^>]*>\s*<p[^>]*>(?<Content>(?(?!</td>)\s*.)*?)</p></td>\s*"
                              + @"</tr>\s*<tr>\s*<td[^>]*>附件</td>\s*"
                              + @"<td[^>]*><p[^>]*>(?<Attachment>(?(?!</p>)\s*.)*?)\s*</p>\s*</td>"
                              , RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);

            regexRe = new Regex(@"<td[^>]*>\s*回复人</td>\s*"
                              + @"<td[^>]*>(?<Author>[^<]*)</td>\s*"
                              + @"<td[^>]*>[^<]*</td>\s*<td[^>]*>(?<PubTime>[^<]*)</td>\s*"
                              + @"<td[^>]*>(?(?!<p)\s*.)*?\s*<p[^>]*>(?<Content>(?(?!</td>)\s*.)*?)\s*</p>\s*</td>\s*"
                              + @"(?(?!<td)\s*.)*?\s*<td[^>]*>[^<]*</td>\s*"
                              + @"<td[^>]*>(?<Attachment>(?(?!</td>)\s*.)*?)\s*</td>"
                              , RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);

            regexAttach = new Regex("<a target=\"_top\" href=\"(?<Link>[^\"]*)\">(?<FileName>\\S*)</a>"
                                    , RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.ExplicitCapture);
            
            regexTableItem = new Regex("<input type=\"hidden\" name=\"(?<Name>[^\"]*)\"( id=\"post_id\"| id=\"post_rec_id\")? value=(\"|')(?<Value>[^'\"]*)(\"|')>"
                                        , RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);
            
            regexEscape = new Regex(@"(&#\d{2,4})|(&nbsp;)", RegexOptions.Compiled | RegexOptions.ExplicitCapture);
        
        }

        private static string AddSemicolon(Match m)
        {
            if (m.Value == "&nbsp;")
                return " ";
            else
                return m.Value + ';';
        }
        private static MatchEvaluator addSemicolon = new MatchEvaluator(AddSemicolon);

        public string CourseId
        {
            get
            {
                return courseId;
            }
        }

        public ThuLearnChannel(string courseId, string title, string username, string password)
        {
            this.courseId = courseId;
            this.title = title;
            this.username = username;
            this.password = password;
            //isOpened = false;
        }

        #region IChannel Members

        public override int GetHashCode()
        {
            return (Category + CourseId + username).GetHashCode();
        }

        public string Title
        {
            get { return title; }
        }

        public string Category
        {
            get { return "网络学堂 - " + username; }
        }

        public string Link
        {
            get { return @"http://learn.tsinghua.edu.cn/lesson/student/course_locate.jsp?course_id=" + CourseId; }
        }

        public string Description
        {
            get { return description; }
        }

        public bool Open()
        {
            if( isOpened == true && (DateTime.Now - lastLoginTime).Minutes <= 10)
                return true;
            else
                return Login();
        }

        public void Close()
        {
            //nothing to do
            return;
        }

        public ICollection<IMessage> GetMessages(DateTime startTime, DateTime endTime, string category)
        {
            switch (category)
            {
                case "课程公告":
                    return GetNotes(startTime, endTime);
                case "课程文件":
                    return GetCourseFiles(startTime, endTime);
                case "课程作业":
                    return GetHomeworks(startTime, endTime);
                case "课程讨论":
                    return GetDiscussions(startTime, endTime);
                default:
                    List<IMessage> messages = new List<IMessage>();
                    if (category == null)   //category==null,则返回全部类别的消息
                    {
                        messages.AddRange(GetNotes(startTime, endTime));
                        messages.AddRange(GetCourseFiles(startTime, endTime));
                        messages.AddRange(GetHomeworks(startTime, endTime));
                        messages.AddRange(GetDiscussions(startTime, endTime));
                    }
                    return messages;
            }
        }

        public Stream DownloadFile(IFileObject file)
        {
            if (!Login())
                return null;

            HttpWebRequest request;
            Stream stream;

            try
            {
                request = (HttpWebRequest)WebRequest.Create(file.FileUri);
                request.Method = "GET";
                request.ContentType = "application/x-www-form-urlencoded";
                request.CookieContainer = cookies;
                stream = request.GetResponse().GetResponseStream();
            }
            catch
            {
                return null;
            }

            return stream;
        }

        public bool RefreshMessage(IMessage message)
        {
            Message msg = message as Message;
            if (msg == null)
                return false;
            switch (msg.Category)
            {
                case "课程公告":
                    return RefreshNote(msg);
                case "课程文件":
                    return RefreshCourseFile(msg);
                case "课程作业":
                    return RefreshHomework(msg);
                case "课程讨论":
                    return RefreshDiscussion(msg);
                default:
                    return false;
            }
        }

        public void NotifyReply(IMessage source)
        {
            Message msg = source as Message;
            if (EditReply == null || source != null && msg == null || EditReply == null)
                return;

            //发表新帖子
            if (msg == null)
            {
                KeyValuePair<string, EditItemType>[] replyItems = new KeyValuePair<string, EditItemType>[4];
                replyItems[0] = new KeyValuePair<string, EditItemType>("标题", EditItemType.SingleLineText);
                replyItems[1] = new KeyValuePair<string, EditItemType>("正文", EditItemType.MultiLineText);
                replyItems[2] = new KeyValuePair<string, EditItemType>("附件", EditItemType.FilePath);
                replyItems[3] = new KeyValuePair<string, EditItemType>("请注意，文本内容不要超过4000字，附件文件名中不要有空格。", EditItemType.StaticText);
                EditReply(this, new EditReplyEventArgs(this, source, replyItems, ""));
            }
            else if (msg.Category == "课程作业")//提交作业
            {
                if (DateTime.Now.Date <= source.DueTime.Date)
                {
                    KeyValuePair<string, EditItemType>[] replyItems = new KeyValuePair<string, EditItemType>[3];
                    replyItems[0] = new KeyValuePair<string, EditItemType>("作业文本", EditItemType.MultiLineText);
                    replyItems[1] = new KeyValuePair<string, EditItemType>("作业附件", EditItemType.FilePath);
                    replyItems[2] = new KeyValuePair<string, EditItemType>("请注意，文本内容不要超过2000字，附件文件名中不要有空格。", EditItemType.StaticText);
                    EditReply(this, new EditReplyEventArgs(this, source, replyItems, ""));
                }
                
                else
                {
                    KeyValuePair<string, EditItemType>[] replyItems = new KeyValuePair<string, EditItemType>[1];
                    replyItems[0] = new KeyValuePair<string, EditItemType>("作业提交截止日期已过。", EditItemType.StaticText);
                    EditReply(this, new EditReplyEventArgs(this, source, replyItems, ""));
                }
            }
            else if (msg.Category == "课程讨论")
            {
                KeyValuePair<string, EditItemType>[] replyItems = new KeyValuePair<string, EditItemType>[3];
                replyItems[0] = new KeyValuePair<string, EditItemType>("正文", EditItemType.MultiLineText);
                replyItems[1] = new KeyValuePair<string, EditItemType>("附件", EditItemType.FilePath);
                replyItems[2] = new KeyValuePair<string, EditItemType>("请注意，正文内容不要超过4000字，附件文件名中不要有空格。", EditItemType.StaticText);
                EditReply(this, new EditReplyEventArgs(this, source, replyItems, ""));
            }
        }

        public bool Reply(IMessage source, IDictionary<string, object> replyinput, string tag)
        {
            if (this.Open() == false)
                return false;
            
            //发表新主题
            if (source == null)
            {
                string title = replyinput["标题"] as string;
                string text = replyinput["正文"] as string;
                string file = replyinput["附件"] as string;
                if (title == null || text == null || file == null)
                {
                    return false;
                }
                //得到发表新话题的链接
                string link;
                try
                {
                    string page = GetWebPage(@"http://learn.tsinghua.edu.cn/public/bbs/gettalkid_student.jsp?course_id=" + CourseId);
                    int i = page.IndexOf("<a id=new_url href=\"");
                    i = page.IndexOf("\"",i);
                    int j = page.IndexOf("\"", i + 1);
                    link = @"http://learn.tsinghua.edu.cn/public/bbs/" + page.Substring(i + 1, j - i - 1);
                }
                catch
                {
                    return false;
                }

                if (file.Length == 0)
                    return PostNewTopicWithoutFile(link, title, text);
                else
                    return PostNewTopicWithFile(link, title, text, file);

            }

            //提交作业或者回复帖子
            Message msg = source as Message;
            if (msg == null)
                return false;

            if (msg.Category == "课程作业")
            {
                string text = replyinput["作业文本"] as string;
                string file = replyinput["作业附件"] as string;
                if (text == null || file == null)
                    return false;

                string link;
                try
                {
                    if ((link = CanSubmitHomework(msg)).Length == 0)
                    {
                        return false;
                    }
                }
                catch
                {
                    return false;
                }

                if (file.Length == 0)
                    return ReplyHomeworkWithoutFile(link, text);
                else
                    return ReplyHomeworkWithFile(link, text, file);
            }
            else if (msg.Category == "课程讨论")
            {
                string text = replyinput["正文"] as string;
                string file = replyinput["附件"] as string;
                if (text == null || file == null)
                    return false;

                string link;
                //得到回复的链接link
                try
                {
                    string page = GetWebPage(msg.Link);
                    int i, j;
                    i = page.IndexOf("<input type");
                    i = page.IndexOf("'", i);
                    j = page.IndexOf("'", i + 1);
                    link = @"http://learn.tsinghua.edu.cn/public/bbs/" + page.Substring(i + 1, j - i - 1);
                }
                catch
                {
                    return false;
                }
                
                if (file.Length == 0)
                    return ReplyDiscussionWithoutFile(link, text);
                else
                    return ReplyDiscussionWithFile(link, text, file);
            }

            return false;
        }

        public event EditReplyEventHandler EditReply;

        #endregion

        #region Private Methods

        private bool Login()
        {
            //获得用户名和密码
            //或者用户名和密码可以作为ThuLearnChannel的私有变量，作为构造函数的参数传进来。

            byte[] data = Encoding.UTF8.GetBytes("userid=" + username + "&userpass=" + password + "&submit1=%B5%C7%C2%BC");

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(@"http://learn.tsinghua.edu.cn/use_go.jsp");
            request.Method = "POST";
            request.Accept = @"image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*";
            request.ContentType = @"application/x-www-form-urlencoded";
            request.ContentLength = data.Length;

            cookies = new CookieContainer();
            request.CookieContainer = cookies;

            Stream reqStream = null;
            HttpWebResponse response = null;
            StreamReader reader = null;
            string responseContent = null;

            try
            {
                reqStream = request.GetRequestStream();
                reqStream.Write(data, 0, data.Length);
                reqStream.Close();

                response = (HttpWebResponse)request.GetResponse();
                reader = new StreamReader(response.GetResponseStream(), Encoding.Default);
                responseContent = reader.ReadToEnd();

                reader.Close();
                response.Close();

                //检查是否登录成功
                if (!responseContent.Contains("/lesson/teacher/main.jsp"))
                    return false;

                //获得CourseId对应的课程信息

                request = (HttpWebRequest)WebRequest.Create(@"http://learn.tsinghua.edu.cn/lesson/student/MyCourse.jsp");
                request.CookieContainer = cookies;

                response = (HttpWebResponse)request.GetResponse();
                reader = new StreamReader(response.GetResponseStream(), Encoding.Default);
                responseContent = reader.ReadToEnd();

                int i = 0, j = 0;
                i = responseContent.IndexOf(courseId, 0);
                if (i == -1)
                    throw new Exception("Wrong courseId!");

                i = responseContent.IndexOf('>', i) + 1;
                j = responseContent.IndexOf("</a>", i);

                description = responseContent.Substring(i, j - i).Trim();
                title = description.Substring(0, description.IndexOf('('));

                reader.Close();
                response.Close();

                isOpened = true;
                lastLoginTime = DateTime.Now;
            }
            catch
            {
                if (reader != null)
                    reader.Close();
                if (response != null)
                    response.Close();
                isOpened = false;
                return false;
            }

            return true;
        }

        //获得uri对应的页面的html
        private string GetWebPage(string uri)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
            request.CookieContainer = cookies;

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.Default);
            string content = reader.ReadToEnd();
            reader.Close();

            return content;
        }

        //获得uri指向的文件的大小
        private long GetFileSize(string uri)
        {
            long filesize = 0;
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
            request.Method = "GET";
            request.ContentType = "application/x-www-form-urlencoded";
            request.CookieContainer = cookies;
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            filesize = response.ContentLength;
            //Console.WriteLine("Filesize: " + filesize + "Bytes");
            response.Close();

            return filesize;
        }

        //对于网络学堂特定的一段html代码(如，点击某个课程作业后打开的页面，查看批阅时的页面)
        //生成对应的附件
        private Attachment makeAttachment(string strAttach, string description)
        {
            Match matAttach = regexAttach.Match(strAttach);

            if (matAttach.Value == "")
                return null;

            string filename = matAttach.Groups["FileName"].Value;
            string filetype;
            long filesize = 0;
            string filelink = @"http://learn.tsinghua.edu.cn" + matAttach.Groups["Link"].Value;

            if (filename.LastIndexOf('.') != -1 && filename[filename.Length - 1] != '.')
                filetype = filename.Substring(filename.LastIndexOf('.') + 1);
            else
                filetype = "File";

            //获得文件大小
            try
            {
                filesize = GetFileSize(filelink);
            }
            catch
            {
                //如果得不到精确的文件大小，就设置为0
                filesize = 0;
            }

            return new Attachment(filename, filetype, filesize, filelink, description);

        }

        //课程公告
        private ICollection<IMessage> GetNotes(DateTime startTime, DateTime endTime)
        {
            string page;
            List<IMessage> messages = new List<IMessage>();

            try
            {
                page = GetWebPage(@"http://learn.tsinghua.edu.cn/public/bbs/getnoteid_student.jsp?course_id=" + CourseId);
            }
            catch
            {
                return messages;
            }

            MatchCollection matches = regexNote.Matches(page);

            foreach (Match match in matches)
            {
                if (DateTime.Parse(match.Groups["Date"].Value) >= startTime && DateTime.Parse(match.Groups["Date"].Value) <= endTime)
                {
                    Message msg = new Message(this);
                    msg.Title = HttpUtility.HtmlDecode(regexEscape.Replace(match.Groups["Title"].Value, addSemicolon)).Trim();
                    msg.Author = match.Groups["Author"].Value;
                    msg.Link = @"http://learn.tsinghua.edu.cn/public/bbs/note_reply.jsp?bbs_type=%bf%ce%b3%cc%b9%ab%b8%e6&" + match.Groups["LinkId"].Value;
                    msg.PubTime = DateTime.Parse(match.Groups["Date"].Value);
                    msg.Category = "课程公告";
                    msg.Description = "一个课程公告";
                    msg.Repliable = false;
                    msg.Read = false;
                    msg.Uid = msg.Link.GetHashCode();

                    string text = GetWebPage(msg.Link);
                    int i, j;
                    i = text.IndexOf("class=\"tableTR\" >正 文");
                    i = text.IndexOf(@"<td", i);
                    i = text.IndexOf(@">", i);
                    j = text.IndexOf("class=\"textTD\"", i);
                    text = text.Substring(i + 1, j - i);
                    j = text.LastIndexOf("</td>");

                    msg.Content = text.Substring(0, j);
                    msg.ContentType = "html";

                    messages.Add(msg);
                }
            }

            return messages;
        }

        //刷新课程公告
        private bool RefreshNote(Message msg)
        {
            //打开原来的网址，查看标题和正文是否改变
            bool changed = false;
            try
            {
                string text = GetWebPage(msg.Link);
                int i, j;
                j = text.IndexOf("标 题");
                i = text.IndexOf("class=\"tableTR\" >正 文");

                //标题
                Match match = regexNoteTitle.Match(text.Substring(j, i - j));
                string t = HttpUtility.HtmlDecode(regexEscape.Replace(match.Groups["Title"].Value, addSemicolon)).Trim();
                if (match != null && t != msg.Title)
                {
                    msg.Title = t;
                    msg.Read = false;
                    changed = true;
                }

                //正文html
                i = text.IndexOf(@"<td", i);
                i = text.IndexOf(@">", i);
                j = text.IndexOf("class=\"textTD\"", i);
                text = text.Substring(i + 1, j - i); ;
                j = text.LastIndexOf("</td>");

                if ((string)(msg.Content) != text.Substring(0, j))
                {
                    msg.Content = text.Substring(0, j);
                    msg.Read = false;
                    changed = true;
                }

                return changed;
            }
            catch
            {
                return false;
            }
        }

        //课程文件
        private ICollection<IMessage> GetCourseFiles(DateTime startTime, DateTime endTime)
        {
            string url = @"http://learn.tsinghua.edu.cn/lesson/student/download.jsp?course_id=" + CourseId;
            string page;

            List<IMessage> messages = new List<IMessage>();

            try
            {
                page = GetWebPage(url);
            }
            catch
            {
                return messages;
            }

            MatchCollection matches = regexFile.Matches(page);
            foreach (Match match in matches)
            {
                if (DateTime.Parse(match.Groups["Date"].Value) >= startTime && DateTime.Parse(match.Groups["Date"].Value) <= endTime)
                {
                    Message msg = new Message(this);
                    msg.Title = HttpUtility.HtmlDecode(regexEscape.Replace(match.Groups["Title"].Value, addSemicolon)).Trim();
                    msg.Link = url;
                    msg.PubTime = DateTime.Parse(match.Groups["Date"].Value);
                    msg.Category = "课程文件";
                    msg.Description = "一个课程文件";
                    msg.Content = match.Groups["Content"].Value;
                    msg.ContentType = "html";
                    msg.Repliable = false;
                    msg.Read = false;
                    msg.Uid = match.Groups["Link"].Value.GetHashCode();


                    //设置附件
                    IList<IFileObject> fos = new List<IFileObject>();
                    string filename = Regex.Replace(match.Groups["FileName"].Value, @"_\d{7,}(\.\w*)$", "$1");
                    string filelink = @"http://learn.tsinghua.edu.cn" + match.Groups["Link"].Value;
                    string filetype;
                    long filesize = 0;

                    if (filename.LastIndexOf('.') != -1 && filename[filename.Length - 1] != '.')
                        filetype = filename.Substring(filename.LastIndexOf('.') + 1);
                    else
                        filetype = "file";

                    //获得文件大小
                    try
                    {
                        filesize = GetFileSize(filelink);
                    }
                    catch
                    {
                        //如果得不到精确的文件大小，就设置为网页上显示的
                        string size = match.Groups["Size"].Value;
                        switch (size[size.Length - 1])
                        {
                            case 'K':
                                filesize = (long)(float.Parse(size.Substring(0, size.Length - 1)) * 1024);
                                break;
                            case 'M':
                                filesize = (long)(float.Parse(size.Substring(0, size.Length - 1)) * 1024 * 1024);
                                break;
                            case 'G':
                                filesize = (long)(float.Parse(size.Substring(0, size.Length - 1)) * 1024 * 1024 * 1024);
                                break;
                            default:
                                filesize = 0;
                                break;
                        }
                    }
                    Attachment att = new Attachment(filename, filetype, filesize, filelink, "附件");
                    fos.Add(att);
                    msg.Attachments = fos;

                    messages.Add(msg);
                }
            }
            return messages;
        }

        //刷新课程文件
        private bool RefreshCourseFile(Message msg)
        {
            //按标题和日期查找，如果标题变化了，则视为无更新。
            try
            {
                bool changed = false;
                string page = GetWebPage(msg.Link);
                
                MatchCollection matches = regexFile.Matches(page);
                foreach (Match match in matches)
                {
                    if (HttpUtility.HtmlDecode(regexEscape.Replace(match.Groups["Title"].Value, addSemicolon)).Trim() == msg.Title && match.Groups["Content"].Value == (string)msg.Content)
                    {
                        string filename = Regex.Replace(match.Groups["FileName"].Value, @"_\d{7,}(\.\w*)$", "$1");
                        string filelink = @"http://learn.tsinghua.edu.cn" + match.Groups["Link"].Value;
                        string filetype;
                        long filesize = 0;

                        if (filename.LastIndexOf('.') != -1 && filename[filename.Length - 1] != '.')
                            filetype = filename.Substring(filename.LastIndexOf('.') + 1);
                        else
                            filetype = "file";

                        //获得文件大小
                        try
                        {
                            filesize = GetFileSize(filelink);
                        }
                        catch
                        {
                            //如果得不到精确的文件大小，就设置为网页上显示的
                            string size = match.Groups["Size"].Value;
                            switch (size[size.Length - 1])
                            {
                                case 'K':
                                    filesize = (long)(float.Parse(size.Substring(0, size.Length - 1)) * 1024);
                                    break;
                                case 'M':
                                    filesize = (long)(float.Parse(size.Substring(0, size.Length - 1)) * 1024 * 1024);
                                    break;
                                case 'G':
                                    filesize = (long)(float.Parse(size.Substring(0, size.Length - 1)) * 1024 * 1024 * 1024);
                                    break;
                                default:
                                    filesize = 0;
                                    break;
                            }
                        }
                        Attachment attach = (msg.Attachments as List<IFileObject>)[0] as Attachment;
                        if (filename != attach.Filename || filelink != attach.FileUri
                            || filetype != attach.FileType || filesize != attach.FileSize)
                        {
                            IList<IFileObject> fos = new List<IFileObject>();
                            fos.Add(new Attachment(filename, filetype, filesize, filelink, "附件"));
                            msg.Attachments = fos;
                            msg.Read = false;
                            changed = true;
                        }

                        return changed;
                    }
                }
                return false;
            }
            catch
            {
                return false;
            }
        }

        //课程作业
        private ICollection<IMessage> GetHomeworks(DateTime startTime, DateTime endTime)
        {
            //作业每次都全部更新
            //startTime = DateTime.MinValue;
            //endTime = DateTime.MaxValue;

            string url = @"http://learn.tsinghua.edu.cn/lesson/student/hom_wk_brw.jsp?course_id=" + CourseId;
            string page;
            List<IMessage> messages = new List<IMessage>();

            try
            {
                page = GetWebPage(url);
            }
            catch
            {
                return messages;
            }

            MatchCollection matches = regexHomework.Matches(page);
            foreach (Match match in matches)
            {
                if (DateTime.Parse(match.Groups["PubTime"].Value) >= startTime && DateTime.Parse(match.Groups["PubTime"].Value) <= endTime)
                {
                    Message msg = new Message(this);
                    msg.Title = HttpUtility.HtmlDecode(regexEscape.Replace(match.Groups["Title"].Value, addSemicolon)).Trim();
                    msg.Link = url;
                    msg.PubTime = DateTime.Parse(match.Groups["PubTime"].Value);
                    msg.DueTime = DateTime.Parse(match.Groups["DueTime"].Value);
                    msg.Category = "课程作业";
                    msg.Description = "一个课程作业";//(" + match.Groups["Status"].Value+")";
                    msg.Read = false;
                    msg.Uid = match.Groups["Link"].Value.GetHashCode();

                    //设置msg.Content和附件
                    string content;
                    string tmp;
                    StringBuilder contentBuilder = new StringBuilder();

                    try
                    { 
                        content = GetWebPage(@"http://learn.tsinghua.edu.cn/lesson/student/" + match.Groups["Link"].Value);
                    }
                    catch
                    {
                        continue;
                    }

                    int i, j;
                    i = content.IndexOf("<textarea");
                    i = content.IndexOf('>', i);
                    j = content.IndexOf("</textarea>", i);

                    //作业说明是第一对<textarea>标签之间的内容，并把换行符替换为<br/>
                    tmp = content.Substring(i + 1, j - i - 1);
                    if (tmp.Trim().Length != 0)
                        contentBuilder.Append("&lt;作业说明&gt;<br/>" + tmp.Replace("\r\n", "<br/>") + "<br/><br/>");
                    else
                        contentBuilder.Append("&lt;作业说明&gt;<br/>无<br/><br/>");

                    //设置附件
                    List<IFileObject> fos = new List<IFileObject>();
                    Attachment att;

                    //作业附件
                    i = content.IndexOf("<td class=\"textTD\">", j);
                    j = content.IndexOf("</td>", i);
                    string strAttach = content.Substring(i + "<td class=\"textTD\">".Length, j - i - "<td class=\"textTD\">".Length);
                    att = makeAttachment(strAttach, "作业附件");
                    if (att != null)
                        fos.Add(att);

                    //上交作业内容
                    i = content.IndexOf("<textarea", j);
                    i = content.IndexOf('>', i);
                    j = content.IndexOf("</textarea>", i);
                    tmp = content.Substring(i + 1, j - i - 1);
                    if (tmp.Trim().Length != 0)
                        contentBuilder.Append("&lt;上交作业内容&gt;<br/>" + tmp.Replace("\r\n", "<br/>") + "<br/><br/>");
                    //else
                    //    contentBuilder.Append("&lt;上交作业内容&gt;<br/>无<br/><br/>");

                    //上交作业附件
                    i = content.IndexOf("<td class=\"textTD\">", j);
                    j = content.IndexOf("</td>", i);
                    strAttach = content.Substring(i + "<td class=\"textTD\">".Length, j - i - "<td class=\"textTD\">".Length);
                    att = makeAttachment(strAttach, "上交作业附件");
                    if (att != null)
                        fos.Add(att);

                    //是否可以提交作业
                    if (match.Groups["Submit"].Value.Length == 0)
                        msg.Repliable = true;
                    else
                        msg.Repliable = false;

                    //是否已经批阅
                    if (match.Groups["Score"].Value.Length == 0)
                    {
                        //已批阅
                        string viewscore = GetWebPage(@"http://learn.tsinghua.edu.cn/lesson/student/hom_wk_view.jsp?id=" + match.Groups["Id"].Value + "&course_id=" + CourseId);
                        int k = viewscore.IndexOf("批阅老师");
                        if (k != -1)
                        {
                            viewscore = viewscore.Substring(k);
                            
                            Match m = regexHomeworkScore.Match(viewscore);
                            if (m.Value.Length != 0)
                            {
                                contentBuilder.Append("<br/>&lt;已批阅&gt;<br/>");
                                if (m.Groups["Teacher"].Value != @"&nbsp;")
                                    contentBuilder.Append("批阅老师:" + m.Groups["Teacher"].Value);
                                contentBuilder.Append("<br/>批阅日期:" + m.Groups["Date"].Value);
                                contentBuilder.Append("<br/>作业得分:" + m.Groups["Score"].Value);
                                contentBuilder.Append("<br/>评语:<br/>  " + m.Groups["Comment"].Value.Replace("\r\n", "<br/>"));
                            }

                            k = viewscore.IndexOf("评语附件");
                            int l = viewscore.IndexOf("<a target", k);
                            if (l != -1)
                            {
                                strAttach = viewscore.Substring(l);
                                //如果存在评语附件，则添加
                                att = makeAttachment(strAttach, "评语附件");
                                if (att != null)
                                    fos.Add(att);
                            }
                        }
                    }
                    contentBuilder.Append("<br/><br/><br/>");
                    msg.Content = contentBuilder.ToString();
                    msg.ContentType = "html";
                    msg.Attachments = fos;

                    messages.Add(msg);
                }
            }

            return messages;
        }

        //刷新课程作业
        private bool RefreshHomework(Message msg)
        {
            string page;
            try
            {
                page = GetWebPage(msg.Link);
            }
            catch
            {
                return false;
            }

            bool changed = false;
            MatchCollection matches = regexHomework.Matches(page);

            foreach (Match match in matches)
            {
                if (HttpUtility.HtmlDecode(regexEscape.Replace(match.Groups["Title"].Value, addSemicolon)).Trim() == msg.Title && DateTime.Parse(match.Groups["PubTime"].Value) == msg.PubTime)
                {
                    if (msg.DueTime != DateTime.Parse(match.Groups["DueTime"].Value))
                    {
                        msg.DueTime = DateTime.Parse(match.Groups["DueTime"].Value);
                        changed = true;
                    }
                    
                    string content = GetWebPage(@"http://learn.tsinghua.edu.cn/lesson/student/" + match.Groups["Link"].Value);
                    string tmp;
                    StringBuilder contentBuilder = new StringBuilder();

                    int i, j;
                    i = content.IndexOf("<textarea");
                    i = content.IndexOf('>', i);
                    j = content.IndexOf("</textarea>", i);

                    //作业说明是第一对<textarea>标签之间的内容，并把换行符替换为<br/>
                    tmp = content.Substring(i + 1, j - i - 1);
                    if (tmp.Trim().Length != 0)
                        contentBuilder.Append("&lt;作业说明&gt;<br/>" + tmp.Replace("\r\n", "<br/>") + "<br/><br/>");
                    else
                        contentBuilder.Append("&lt;作业说明&gt;<br/>无<br/><br/>");


                    //设置附件
                    List<IFileObject> fos = new List<IFileObject>();
                    Attachment att;
                    bool repliable;

                    //作业附件
                    i = content.IndexOf("<td class=\"textTD\">", j);
                    j = content.IndexOf("</td>", i);
                    string strAttach = content.Substring(i + "<td class=\"textTD\">".Length, j - i - "<td class=\"textTD\">".Length);
                    att = makeAttachment(strAttach, "作业附件");
                    if (att != null)
                        fos.Add(att);

                    //上交作业内容
                    i = content.IndexOf("<textarea", j);
                    i = content.IndexOf('>', i);
                    j = content.IndexOf("</textarea>", i);
                    tmp = content.Substring(i + 1, j - i - 1);
                    if (tmp.Trim().Length != 0)
                        contentBuilder.Append("&lt;上交作业内容&gt;<br/>" + tmp.Replace("\r\n", "<br/>") + "<br/><br/>");
                    //else
                    //    contentBuilder.Append("&lt;上交作业内容&gt;<br/>无<br/><br/>");                    
                      
                    //上交作业附件
                    i = content.IndexOf("<td class=\"textTD\">", j);
                    j = content.IndexOf("</td>", i);
                    strAttach = content.Substring(i + "<td class=\"textTD\">".Length, j - i - "<td class=\"textTD\">".Length);
                    att = makeAttachment(strAttach, "上交作业附件");
                    if (att != null)
                        fos.Add(att);

                    //是否可以提交作业
                    if (match.Groups["Submit"].Value.Length == 0)
                        repliable = true;
                    else
                        repliable = false;

                    //是否已经批阅
                    if (match.Groups["Score"].Value.Length == 0)
                    {
                        //已批阅
                        string viewscore = GetWebPage(@"http://learn.tsinghua.edu.cn/lesson/student/hom_wk_view.jsp?id=" + match.Groups["Id"].Value + "&course_id=" + CourseId);
                        int k = viewscore.IndexOf("批阅老师");
                        if (k != -1)
                        {
                            viewscore = viewscore.Substring(k);
                            
                            Match m = regexHomeworkScore.Match(viewscore);
                            if (m.Value.Length != 0)
                            {
                                contentBuilder.Append("<br/>&lt;已批阅&gt;<br/>");
                                if (m.Groups["Teacher"].Value != @"&nbsp;")
                                    contentBuilder.Append("批阅老师:" + m.Groups["Teacher"].Value);
                                contentBuilder.Append("<br/>批阅日期:" + m.Groups["Date"].Value);
                                contentBuilder.Append("<br/>作业得分:" + m.Groups["Score"].Value);
                                contentBuilder.Append("<br/>评语:<br/>  " + m.Groups["Comment"].Value.Replace("\r\n", "<br/>"));
                            }

                            k = viewscore.IndexOf("评语附件");
                            int l = viewscore.IndexOf("<a target", k);
                            if (l != -1)
                            {
                                strAttach = viewscore.Substring(l);
                                //如果存在评语附件，则添加
                                att = makeAttachment(strAttach, "评语附件");
                                if (att != null)
                                    fos.Add(att);
                            }
                        }
                    }
                    contentBuilder.Append("<br/><br/><br/>");
                    string msgContent = contentBuilder.ToString();
                    if (changed == true || (string)msg.Content != msgContent || msg.Repliable != repliable)
                    {
                        msg.Content = msgContent;
                        msg.Repliable = repliable;
                        msg.Attachments = fos;
                        msg.Read = false;
                        return true;
                    }
                    else
                    {
                        if (msg.Attachments.Count != fos.Count)
                        {
                            msg.Attachments = fos;
                            msg.Read = false;
                            return true;
                        }
                        else
                        {
                            List<IFileObject> atts = (List<IFileObject>)msg.Attachments;
                            for (int k = 0; k != fos.Count; k++)
                            {
                                if (!((Attachment)atts[k]).Equals((Attachment)fos[k]))
                                {
                                    msg.Attachments = fos;
                                    msg.Read = false;
                                    return true;
                                }
                            }
                        }
                    }
                }
            }
            return false;
        }

        private bool BuildDiscussionContentAndAttachment(string text, out string title, out string pubtime, out string content, out List<IFileObject> fos)
        {
            StringBuilder contentBuilder = new StringBuilder();
            Attachment att;
            fos = new List<IFileObject>();
            Match lz = regexLz.Match(text);

            title = HttpUtility.HtmlDecode(regexEscape.Replace(lz.Groups["Title"].Value, addSemicolon)).Trim();
            pubtime = HttpUtility.HtmlDecode(regexEscape.Replace(lz.Groups["PubTime"].Value, addSemicolon)).Trim();
            contentBuilder.Append("<p><b>["
                                + HttpUtility.HtmlDecode(regexEscape.Replace(lz.Groups["Author"].Value, addSemicolon)).Trim()
                                + "  " + pubtime
                                + "]</b><br/>");
            contentBuilder.Append(lz.Groups["Content"]);
            contentBuilder.Append("<br/><br/>");

            if (!lz.Groups["Attachment"].Value.Contains("无附件"))
            {
                try
                {
                    att = makeAttachment(lz.Groups["Attachment"].Value, "附件");
                }
                catch
                {
                    att = null;
                }
                if (att != null)
                {
                    fos.Add(att);
                    contentBuilder.Append("附件: " + att.Filename + "<br/>");
                }
            }
            contentBuilder.Append("</p>\r\n");


            MatchCollection res = regexRe.Matches(text);
            foreach (Match re in res)
            {
                contentBuilder.Append("<p><b>[" + re.Groups["Author"].Value.Trim() + "  " + re.Groups["PubTime"].Value.Trim() + "]</b><br/>");
                contentBuilder.Append(re.Groups["Content"]);
                contentBuilder.Append("<br/><br/>");


                if (!re.Groups["Attachment"].Value.Contains("无附件"))
                {
                    try
                    {
                        att = makeAttachment(re.Groups["Attachment"].Value, "附件");
                    }
                    catch
                    {
                        att = null;
                    }
                    if (att != null)
                    {
                        fos.Add(att);
                        contentBuilder.Append("附件: " + att.Filename + "<br/>");
                    }
                }
                contentBuilder.Append("</p>");
            }
            contentBuilder.Append("<br/><br/><br/>");
            content = contentBuilder.ToString();

            return true;
        }

        //课程讨论
        private ICollection<IMessage> GetDiscussions(DateTime startTime, DateTime endTime)
        {
            string url = @"http://learn.tsinghua.edu.cn/public/bbs/gettalkid_student.jsp?course_id=" + CourseId;
            string page;
            List<IMessage> messages = new List<IMessage>();

            try
            {
                page = GetWebPage(url);
            }
            catch
            {
                return messages;
            }

            MatchCollection matches = regexDiscussTopic.Matches(page);
            foreach (Match match in matches)
            {
                if (DateTime.Parse(match.Groups["PubTime"].Value) >= startTime && DateTime.Parse(match.Groups["PubTime"].Value) <= endTime)
                {
                    Message msg = new Message(this);
                    msg.Link = @"http://learn.tsinghua.edu.cn/public/bbs/" + match.Groups["Link"].Value;
                    msg.Author = match.Groups["Author"].Value.Trim();
                    msg.Category = "课程讨论";
                    msg.Description = "一个课程讨论";
                    msg.Read = false;
                    msg.Uid = match.Groups["Link"].Value.GetHashCode();
                    msg.Repliable = true;
                    msg.ContentType = "html";

                    //设置msg.Content和附件
                    string text;
                    string title;
                    string pubtime;
                    string content;
                    List<IFileObject> fos;

                    try
                    {
                        text = GetWebPage(msg.Link);
                    }
                    catch
                    {
                        continue;
                    }

                    if (BuildDiscussionContentAndAttachment(text, out title, out pubtime, out content, out fos) == false)
                        continue;

                    msg.Title = title;

                    try
                    {
                        msg.PubTime = DateTime.Parse(pubtime);
                    }
                    catch
                    {
                        continue;
                    }

                    msg.Content = content;

                    if (fos.Count != 0)
                        msg.Attachments = fos;

                    messages.Add(msg);
                }
            }

            return messages;
        }

        //刷新课程作业
        private bool RefreshDiscussion(Message msg)
        {
            string text;
            string title;
            string pubtime;
            string content;
            List<IFileObject> fos;
            //bool changed = false;

            try
            {
                text = GetWebPage(msg.Link);
            }
            catch
            {
                return false;
            }

            if (BuildDiscussionContentAndAttachment(text, out title, out pubtime, out content, out fos) == false)
                return false;

            if (msg.Title != title || msg.PubTime != DateTime.Parse(pubtime) || content != (string)msg.Content)
            {
                msg.Title = title;
                try
                {

                    msg.PubTime = DateTime.Parse(pubtime);
                }
                catch
                {
                    return false;
                }
                msg.Content = content;
                msg.Attachments = fos;
                msg.Read = false;

                return true;
            }
            else
            {
                if (msg.Attachments.Count != fos.Count)
                {
                    msg.Attachments = fos;
                    msg.Read = false;
                    return true;
                }
                else
                {
                    List<IFileObject> atts = (List<IFileObject>)msg.Attachments;
                    for (int k = 0; k != fos.Count; k++)
                    {
                        if (!((Attachment)atts[k]).Equals((Attachment)fos[k]))
                        {
                            msg.Attachments = fos;
                            msg.Read = false;
                            return true;
                        }
                    }
                }
            }
            return false;
        }

        //check作业是否过期。如果过期，则返回空字符串""；否则返回提交作业页面的地址
        private string CanSubmitHomework(Message msg)
        {
            string page;
            try
            {
                page = GetWebPage(msg.Link);
            }
            catch
            {
                return "";
            }

            MatchCollection matches = regexHomework.Matches(page);
            foreach (Match match in matches)
            {
                if (HttpUtility.HtmlDecode(regexEscape.Replace(match.Groups["Title"].Value, addSemicolon)).Trim() == msg.Title && DateTime.Parse(match.Groups["PubTime"].Value) == msg.PubTime)
                {
                    if (match.Groups["Submit"].Value.Length == 0)
                        return @"http://learn.tsinghua.edu.cn/lesson/student/" + match.Groups["SubmitPage"].Value;
                    break;
                }
            }
            return "";
        }

        private bool ReplyHomeworkWithoutFile(string link, string text)
        {
            try
            {
                string str = GetWebPage(link);
                StringBuilder sb = new StringBuilder();

                MatchCollection ms = regexTableItem.Matches(str);
                foreach (Match m in ms)
                {
                    sb.Append(m.Groups["Name"].Value);
                    sb.Append("=");
                    sb.Append(HttpUtility.UrlEncode(m.Groups["Value"].Value, Encoding.GetEncoding("GB2312")));
                    sb.Append("&");
                }
                sb.Append("filename=&");
                sb.Append("post_rec_homewk_detail=");
                sb.Append(HttpUtility.UrlEncode(text, Encoding.GetEncoding("GB2312")));
                sb.Append("&upfile=");

                byte[] content = Encoding.UTF8.GetBytes(sb.ToString());

                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(@"http://learn.tsinghua.edu.cn/lesson/student/hom_wk_handin.jsp");
                request.Method = "POST";
                //request.Accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-ms-application, application/vnd.ms-xpsdocument, application/xaml+xml, application/x-ms-xbap, application/x-silverlight, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*";
                request.ContentType = "application/x-www-form-urlencoded";
                request.ContentLength = content.Length;
                request.CookieContainer = cookies;

                Stream reqStream = request.GetRequestStream();
                reqStream.Write(content, 0, content.Length);
                reqStream.Close();

                StreamReader reader = new StreamReader(request.GetResponse().GetResponseStream());
                reader.ReadToEnd();
                //这里可以加上错误检测
                return true;
            }
            catch
            {
                return false;
            }
        }

        private bool ReplyHomeworkWithFile(string link, string text, string file)
        {
            
            FileInfo fileinfo = new FileInfo(file);
            
            //不能有空格
            if (fileinfo.Name.Contains(' '))
                return false;

            try
            {
                string str = GetWebPage(link);
                string boundary = "---------------------------7d84e143e0330";

                StringBuilder sb = new StringBuilder(boundary);
                sb.Append("\r\n");
                StringBuilder sbtext = new StringBuilder();
                string newfile = null;
                
                MatchCollection ms = regexTableItem.Matches(str);
                foreach (Match m in ms)
                {
                    if (m.Groups["Name"].Value == "post_homewk_link")
                        continue;
                    if (m.Groups["Name"].Value == "newfilename")
                        newfile = m.Groups["Value"].Value;
                    sb.Append("Content-Disposition: form-data; name=");
                    sb.Append("\"" + m.Groups["Name"].Value + "\"");
                    sbtext.Append(HttpUtility.UrlEncode(m.Groups["Name"].Value, Encoding.GetEncoding("GB2312")));
                    sb.Append("\r\n\r\n");
                    sb.Append(m.Groups["Value"].Value);
                    sbtext.Append("=" + HttpUtility.UrlEncode(m.Groups["Value"].Value, Encoding.GetEncoding("GB2312")));
                    sb.Append("\r\n" + boundary + "\r\n");
                    sbtext.Append("&");
                }

                Random r = new Random();
                sb.Append("Content-Disposition: form-data; name=\"filename\"\r\n\r\n");
                newfile += (Math.Round(10000 * r.NextDouble()).ToString() + '0' + Math.Round(10000 * r.NextDouble()).ToString() + "_" + fileinfo.Name);
                sb.Append(newfile);
                sb.Append("\r\n" + boundary + "\r\n");
                sbtext.Append("filename=" + HttpUtility.UrlEncode(newfile, Encoding.GetEncoding("GB2312")) + "&");

                sb.Append("Content-Disposition: form-data; name=\"post_homewk_link\"\r\n\r\n");
                sb.Append(newfile);
                sb.Append("\r\n" + boundary + "\r\n");
                sbtext.Append("post_homewk_link=" + HttpUtility.UrlEncode(newfile, Encoding.GetEncoding("GB2312")) + "&");

                //用户作业文本
                sb.Append("Content-Disposition: form-data; name=\"post_rec_homewk_detail\"\r\n\r\n");
                sb.Append(text);
                sb.Append("\r\n" + boundary + "\r\n");

                sbtext.Append("post_rec_homewk_detail=");
                sbtext.Append(HttpUtility.UrlEncode(text, Encoding.GetEncoding("GB2312")));
                //sbtext.Append("&Submit=" + HttpUtility.UrlEncode("提交", Encoding.GetEncoding("GB2312")) + "&tj=" + HttpUtility.UrlEncode("确定", Encoding.GetEncoding("GB2312")));
                sbtext.Append("&Submit=%cc%e1%bd%bb&tj=%c8%b7%b6%a8");

                //作业附件
                sb.Append("Content-Disposition: form-data; name=\"upfile\"; filename=\"");
                sb.Append(fileinfo.FullName);
                sb.Append("\"\r\nContent-Type: application/octet-stream\r\n\r\n");

                byte[] part1 = Encoding.GetEncoding("GB2312").GetBytes(sb.ToString());
                byte[] part2 = File.ReadAllBytes(fileinfo.FullName);
                string part3str = "\r\n" + boundary + "\r\nContent-Disposition: form-data; name=\"Submit\"\r\n\r\n提交\r\n" + boundary + "--";
                byte[] part3 = Encoding.GetEncoding("GB2312").GetBytes(part3str);

                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(@"http://learn.tsinghua.edu.cn/uploadFile/uploadFile.jsp");
                request.Method = "POST";
                request.ContentType = "multipart/form-data; boundary=" + boundary.Substring(2);
                request.ContentLength = part1.Length + part2.Length + part3.Length;
                request.CookieContainer = cookies;

                Stream reqStream = request.GetRequestStream();
                reqStream.Write(part1, 0, part1.Length);
                reqStream.Write(part2, 0, part2.Length);
                reqStream.Write(part3, 0, part3.Length);
                reqStream.Close();

                StreamReader reader = new StreamReader(request.GetResponse().GetResponseStream());
                reader.ReadToEnd();
                //这里可加上错误检测


                byte[] content = Encoding.UTF8.GetBytes(sbtext.ToString());
                request = (HttpWebRequest)WebRequest.Create(@"http://learn.tsinghua.edu.cn/lesson/student/hom_wk_handin.jsp");
                request.Method = "POST";
                request.ContentType = "application/x-www-form-urlencoded";
                request.ContentLength = content.Length;
                request.CookieContainer = cookies;

                reqStream = request.GetRequestStream();
                reqStream.Write(content, 0, content.Length);
                reqStream.Close();

                reader = new StreamReader(request.GetResponse().GetResponseStream());
                reader.ReadToEnd();
                //这里可加上错误检测

                return true;
            }
            catch
            {
                return false;
            }
        }

        private bool ReplyDiscussionWithoutFile(string link, string text)
        {
            try
            {
                string str = GetWebPage(link);
                StringBuilder sb = new StringBuilder();

                MatchCollection ms = regexTableItem.Matches(str);
                foreach (Match m in ms)
                {
                    sb.Append(m.Groups["Name"].Value);
                    sb.Append("=");
                    sb.Append(HttpUtility.UrlEncode(m.Groups["Value"].Value, Encoding.GetEncoding("GB2312")));
                    sb.Append("&");
                }
                sb.Append("filename=&");
                sb.Append("post_detail=");
                sb.Append(HttpUtility.UrlEncode(text, Encoding.GetEncoding("GB2312")));
                sb.Append("&upfile=");
                sb.Append("&Submit=%CC%E1+%BD%BB");

                byte[] content = Encoding.UTF8.GetBytes(sb.ToString());

                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(@"http://learn.tsinghua.edu.cn/public/bbs/bbs_talk_reply_submit.jsp");
                request.Method = "POST";
                //request.Accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-ms-application, application/vnd.ms-xpsdocument, application/xaml+xml, application/x-ms-xbap, application/x-silverlight, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*";
                request.ContentType = "application/x-www-form-urlencoded";
                request.ContentLength = content.Length;
                request.CookieContainer = cookies;

                Stream reqStream = request.GetRequestStream();
                reqStream.Write(content, 0, content.Length);
                reqStream.Close();

                StreamReader reader = new StreamReader(request.GetResponse().GetResponseStream());
                reader.ReadToEnd();
                //这里可以加上错误检测
                return true;
            }
            catch
            {
                return false;
            }
        }

        private bool ReplyDiscussionWithFile(string link, string text, string file)
        {
            FileInfo fileinfo = new FileInfo(file);

            //不能有空格
            if (fileinfo.Name.Contains(' '))
                return false;

            try
            {
                string str = GetWebPage(link);
                string boundary = "---------------------------7d84e143e0330";

                StringBuilder sb = new StringBuilder(boundary);
                sb.Append("\r\n");
                StringBuilder sbtext = new StringBuilder();
                string filename = null;

                MatchCollection ms = regexTableItem.Matches(str);
                foreach (Match m in ms)
                {
                    if (m.Groups["Name"].Value == "post_file_link")
                        continue;
                    sb.Append("Content-Disposition: form-data; name=");
                    sb.Append("\"" + m.Groups["Name"].Value + "\"");
                    sbtext.Append(HttpUtility.UrlEncode(m.Groups["Name"].Value, Encoding.GetEncoding("GB2312")));
                    sb.Append("\r\n\r\n");
                    sb.Append(m.Groups["Value"].Value);
                    sbtext.Append("=" + HttpUtility.UrlEncode(m.Groups["Value"].Value, Encoding.GetEncoding("GB2312")));
                    sb.Append("\r\n" + boundary + "\r\n");
                    sbtext.Append("&");
                }

                Random r = new Random();
                sb.Append("Content-Disposition: form-data; name=\"filename\"\r\n\r\n");
                filename += (Math.Round(10000 * r.NextDouble()).ToString() + '0' + Math.Round(10000 * r.NextDouble()).ToString() + "_" + fileinfo.Name);
                sb.Append(filename);
                sb.Append("\r\n" + boundary + "\r\n");
                sbtext.Append("filename=" + HttpUtility.UrlEncode(filename, Encoding.GetEncoding("GB2312")) + "&");

                sb.Append("Content-Disposition: form-data; name=\"post_file_link\"\r\n\r\n");
                sb.Append(filename);
                sb.Append("\r\n" + boundary + "\r\n");
                sbtext.Append("post_file_link=" + HttpUtility.UrlEncode(filename, Encoding.GetEncoding("GB2312")) + "&");

                //文本
                sb.Append("Content-Disposition: form-data; name=\"post_detail\"\r\n\r\n");
                sb.Append(text);
                sb.Append("\r\n" + boundary + "\r\n");

                sbtext.Append("post_detail=");
                sbtext.Append(HttpUtility.UrlEncode(text, Encoding.GetEncoding("GB2312")));
                //sbtext.Append("&Submit=" + HttpUtility.UrlEncode("提交", Encoding.GetEncoding("GB2312")) + "&tj=" + HttpUtility.UrlEncode("确定", Encoding.GetEncoding("GB2312")));
                sbtext.Append("&Submit=%CC%E1+%BD%BB&tj=%C8%B7%B6%A8");

                //附件
                sb.Append("Content-Disposition: form-data; name=\"upfile\"; filename=\"");
                sb.Append(fileinfo.FullName);
                sb.Append("\"\r\nContent-Type: application/octet-stream\r\n\r\n");

                byte[] part1 = Encoding.GetEncoding("GB2312").GetBytes(sb.ToString());
                byte[] part2 = File.ReadAllBytes(fileinfo.FullName);
                string part3str = "\r\n" + boundary + "\r\nContent-Disposition: form-data; name=\"Submit\"\r\n\r\n提 交\r\n" + boundary + "--";
                byte[] part3 = Encoding.GetEncoding("GB2312").GetBytes(part3str);

                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(@"http://learn.tsinghua.edu.cn/uploadFile/uploadFile.jsp");
                request.Method = "POST";
                request.ContentType = "multipart/form-data; boundary=" + boundary.Substring(2);
                request.ContentLength = part1.Length + part2.Length + part3.Length;
                request.CookieContainer = cookies;

                Stream reqStream = request.GetRequestStream();
                reqStream.Write(part1, 0, part1.Length);
                reqStream.Write(part2, 0, part2.Length);
                reqStream.Write(part3, 0, part3.Length);
                reqStream.Close();

                StreamReader reader = new StreamReader(request.GetResponse().GetResponseStream());
                reader.ReadToEnd();
                //这里可加上错误检测


                byte[] content = Encoding.UTF8.GetBytes(sbtext.ToString());
                request = (HttpWebRequest)WebRequest.Create(@"http://learn.tsinghua.edu.cn/public/bbs/bbs_talk_reply_submit.jsp");
                request.Method = "POST";
                request.ContentType = "application/x-www-form-urlencoded";
                request.ContentLength = content.Length;
                request.CookieContainer = cookies;

                reqStream = request.GetRequestStream();
                reqStream.Write(content, 0, content.Length);
                reqStream.Close();

                reader = new StreamReader(request.GetResponse().GetResponseStream());
                reader.ReadToEnd();
                //这里可加上错误检测

                return true;
            }
            catch
            {
                return false;
            }
        }

        private bool PostNewTopicWithoutFile(string link, string title, string text)
        {
            try
            {
                string str = GetWebPage(link);
                StringBuilder sb = new StringBuilder();

                MatchCollection ms = regexTableItem.Matches(str);
                foreach (Match m in ms)
                {
                    sb.Append(m.Groups["Name"].Value);
                    sb.Append("=");
                    sb.Append(HttpUtility.UrlEncode(m.Groups["Value"].Value, Encoding.GetEncoding("GB2312")));
                    sb.Append("&");
                }
                sb.Append("filename=");
                sb.Append("&post_cate_id=1");
                sb.Append("&post_title=");
                sb.Append(HttpUtility.UrlEncode(title, Encoding.GetEncoding("GB2312")));
                sb.Append("&post_detail=");
                sb.Append(HttpUtility.UrlEncode(text, Encoding.GetEncoding("GB2312")));
                sb.Append("&upfile=");
                sb.Append("&Submit=%CC%E1+%BD%BB");

                byte[] content = Encoding.UTF8.GetBytes(sb.ToString());

                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(@"http://learn.tsinghua.edu.cn/public/bbs/bbs_talk_submit.jsp");
                request.Method = "POST";
                //request.Accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-ms-application, application/vnd.ms-xpsdocument, application/xaml+xml, application/x-ms-xbap, application/x-silverlight, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*";
                request.ContentType = "application/x-www-form-urlencoded";
                request.ContentLength = content.Length;
                request.CookieContainer = cookies;

                Stream reqStream = request.GetRequestStream();
                reqStream.Write(content, 0, content.Length);
                reqStream.Close();

                StreamReader reader = new StreamReader(request.GetResponse().GetResponseStream());
                reader.ReadToEnd();
                //这里可以加上错误检测
                return true;
            }
            catch
            {
                return false;
            }
        }

        private bool PostNewTopicWithFile(string link, string title, string text, string file)
        {            
            FileInfo fileinfo = new FileInfo(file);
            //不能有空格
            if (fileinfo.Name.Contains(' '))
                return false;

            try
            {
                string str = GetWebPage(link);
                string boundary = "---------------------------7d84e143e0330";

                StringBuilder sb = new StringBuilder(boundary);
                sb.Append("\r\n");
                StringBuilder sbtext = new StringBuilder();
                string filename = null;

                MatchCollection ms = regexTableItem.Matches(str);
                foreach (Match m in ms)
                {
                    if (m.Groups["Name"].Value == "post_file_link")
                        continue;
                    sb.Append("Content-Disposition: form-data; name=");
                    sb.Append("\"" + m.Groups["Name"].Value + "\"");
                    sbtext.Append(HttpUtility.UrlEncode(m.Groups["Name"].Value, Encoding.GetEncoding("GB2312")));
                    sb.Append("\r\n\r\n");
                    sb.Append(m.Groups["Value"].Value);
                    sbtext.Append("=" + HttpUtility.UrlEncode(m.Groups["Value"].Value, Encoding.GetEncoding("GB2312")));
                    sb.Append("\r\n" + boundary + "\r\n");
                    sbtext.Append("&");
                }

                Random r = new Random();
                sb.Append("Content-Disposition: form-data; name=\"filename\"\r\n\r\n");
                filename += (Math.Round(10000 * r.NextDouble()).ToString() + '0' + Math.Round(10000 * r.NextDouble()).ToString() + "_" + fileinfo.Name);
                sb.Append(filename);
                sb.Append("\r\n" + boundary + "\r\n");
                sbtext.Append("filename=" + HttpUtility.UrlEncode(filename, Encoding.GetEncoding("GB2312")) + "&");

                sb.Append("Content-Disposition: form-data; name=\"post_file_link\"\r\n\r\n");
                sb.Append(filename);
                sb.Append("\r\n" + boundary + "\r\n");
                sbtext.Append("post_file_link=" + HttpUtility.UrlEncode(filename, Encoding.GetEncoding("GB2312")) + "&");

                //post_cate_id
                sb.Append("Content-Disposition: form-data; name=\"post_cate_id=\"\r\n\r\n");
                sb.Append("1");
                sb.Append("\r\n" + boundary + "\r\n");
                sbtext.Append("post_cate_id=1&");

                //标题
                sb.Append("Content-Disposition: form-data; name=\"post_title\"\r\n\r\n");
                sb.Append(title);
                sb.Append("\r\n" + boundary + "\r\n");

                sbtext.Append("post_title=");
                sbtext.Append(HttpUtility.UrlEncode(title, Encoding.GetEncoding("GB2312")) + "&");

                //正文
                sb.Append("Content-Disposition: form-data; name=\"post_detail\"\r\n\r\n");
                sb.Append(text);
                sb.Append("\r\n" + boundary + "\r\n");

                sbtext.Append("post_detail=");
                sbtext.Append(HttpUtility.UrlEncode(text, Encoding.GetEncoding("GB2312")));
                
                //提交,确认
                sbtext.Append("&Submit=%CC%E1+%BD%BB&tj=%C8%B7%B6%A8");
                //sbtext.Append("&Submit=" + HttpUtility.UrlEncode("提 交", Encoding.GetEncoding("GB2312")) + "&tj=" + HttpUtility.UrlEncode("确定", Encoding.GetEncoding("GB2312")));
                
                //附件
                sb.Append("Content-Disposition: form-data; name=\"upfile\"; filename=\"");
                sb.Append(fileinfo.FullName);
                sb.Append("\"\r\nContent-Type: application/octet-stream\r\n\r\n");

                byte[] part1 = Encoding.GetEncoding("GB2312").GetBytes(sb.ToString());
                byte[] part2 = File.ReadAllBytes(fileinfo.FullName);
                string part3str = "\r\n" + boundary + "\r\nContent-Disposition: form-data; name=\"Submit\"\r\n\r\n提 交\r\n" + boundary + "--";
                byte[] part3 = Encoding.GetEncoding("GB2312").GetBytes(part3str);

                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(@"http://learn.tsinghua.edu.cn/uploadFile/uploadFile.jsp");
                request.Method = "POST";
                request.ContentType = "multipart/form-data; boundary=" + boundary.Substring(2);
                request.ContentLength = part1.Length + part2.Length + part3.Length;
                request.CookieContainer = cookies;

                Stream reqStream = request.GetRequestStream();
                reqStream.Write(part1, 0, part1.Length);
                reqStream.Write(part2, 0, part2.Length);
                reqStream.Write(part3, 0, part3.Length);
                reqStream.Close();

                StreamReader reader = new StreamReader(request.GetResponse().GetResponseStream());
                reader.ReadToEnd();
                //这里可加上错误检测


                byte[] content = Encoding.UTF8.GetBytes(sbtext.ToString());
                request = (HttpWebRequest)WebRequest.Create(@"http://learn.tsinghua.edu.cn/public/bbs/bbs_talk_reply_submit.jsp");
                request.Method = "POST";
                request.ContentType = "application/x-www-form-urlencoded";
                request.ContentLength = content.Length;
                request.CookieContainer = cookies;

                reqStream = request.GetRequestStream();
                reqStream.Write(content, 0, content.Length);
                reqStream.Close();

                reader = new StreamReader(request.GetResponse().GetResponseStream());
                reader.ReadToEnd();
                //这里可加上错误检测

                return true;
            }
            catch
            {
                return false;
            }
        }

        #endregion


        #region IChannel 成员


        public DateTime LastUpdateTime
        {
            get;
            set;
        }

        #endregion
    }
}
